﻿using AutoMapper;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.EntityFrameworkCore;
using Microsoft.Win32;
using Rj_GsInsurance.Server.DataBaseContext;
using Rj_GsInsurance.Server.DataBaseContext.Entities;
using Rj_GsInsurance.Server.Extensions;
using Rj_GsInsurance.Server.Models;
using Rj_GsInsurance.Server.Models.InsurCatalogue;
using Rj_GsInsurance.Server.Models.InsurMsgDataInput;
using Rj_GsInsurance.Server.Models.InsurMsgDataOutput;
using Rj_GsInsurance.Server.Services;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;
using Wpf.Ui;
using Wpf.Ui.Controls;

namespace Rj_GsInsurance.Client.ViewModels
{
    public partial class InsurDownLoadViewModel : ObservableObject
    {
        [ObservableProperty]
        private List<InsurTypeCode> _CatalogueTypeCoding = InsurDict.CatalogueTypeCoding;

        [ObservableProperty]
        private DateTime? _LastDownDate;

        [ObservableProperty]
        private string _CatalogueType = string.Empty;
        [ObservableProperty]
        private string _FileFullName = string.Empty;

        private IGsInsuranceServer GsInsuranceServer;

        public ISnackbarService SnackbarService { get; set; }

        private HisDbContext HisDbContext;
        private IMapper Mapper;

        public InsurDownLoadViewModel(IGsInsuranceServer gsInsuranceServer, ISnackbarService snackbarService, HisDbContext hisDbContext, IMapper mapper)
        {
            this.GsInsuranceServer = gsInsuranceServer;
            this.SnackbarService = snackbarService;
            this.HisDbContext = hisDbContext;
            this.Mapper = mapper;
            LastDownDate = DateTime.Now;
        }
        [RelayCommand]
        private async Task OnDownLoad(object param)
        {
            if (string.IsNullOrWhiteSpace(this.CatalogueType))
            {
                SnackbarService.Show(
                    "警告!",
                    $"请选择下载类别",
                    ControlAppearance.Danger,
                    new SymbolIcon(SymbolRegular.Fluent24),
                    TimeSpan.FromSeconds(30)
                );
                return;
            }
            if (this.LastDownDate == null)
            {
                SnackbarService.Show(
                    "警告!",
                    $"请选择最后下载日期",
                    ControlAppearance.Danger,
                    new SymbolIcon(SymbolRegular.Fluent24),
                    TimeSpan.FromSeconds(30)
                );
                return;
            }
            DownLoadInput input = new DownLoadInput()
            {
                DataType = this.CatalogueType,
                BeginTime = this.LastDownDate?.ToString("yyyyMMddHHmmss"),
            };
            try
            {
                var insurMsgOut = await input.ExcuteSync<DownLoadInput, DownLoadOutput>("1300");
                this.FileFullName = insurMsgOut.output.FileFullName;
            }
            catch (Exception ex)
            {
                SnackbarService.Show(
                    "警告!",
                    $"医保交易失败!{ex.Message}",
                    ControlAppearance.Danger,
                    new SymbolIcon(SymbolRegular.Fluent24),
                    TimeSpan.FromSeconds(30)
                );
                return;
            }
        }
        [RelayCommand]
        private async Task OnImport(object param)
        {
            if (string.IsNullOrWhiteSpace(this.CatalogueType))
            {
                SnackbarService.Show(
                    "警告!",
                    $"请选择导入类别",
                    ControlAppearance.Danger,
                    new SymbolIcon(SymbolRegular.Fluent24),
                    TimeSpan.FromSeconds(30)
                );
                return;
            }
            if (string.IsNullOrWhiteSpace(this.FileFullName))
            {
                SnackbarService.Show(
                    "警告!",
                    $"请选择导入文件",
                    ControlAppearance.Danger,
                    new SymbolIcon(SymbolRegular.Fluent24),
                    TimeSpan.FromSeconds(30)
                );
                return;
            }
            await Task.Run(() =>
            {
                switch (this.CatalogueType)
                {
                    case "01"://药品
                        var drugs = FileSerialize<Drug>(this.FileFullName);
                        List<InsurWorkInjuryCatalogueDrug> catalogueDrugs = new List<InsurWorkInjuryCatalogueDrug>();
                        foreach (var item in drugs)
                        {
                            if (HisDbContext.InsurWorkInjuryCatalogueDrugs.Any(a => a.DrugCode == item.DrugCode))
                            {
                                var durg = HisDbContext.InsurWorkInjuryCatalogueDrugs.Find(item.DrugCode);
                                HisDbContext.InsurWorkInjuryCatalogueDrugs.Remove(durg);
                            }
                            var catalogueDrug = Mapper.Map<InsurWorkInjuryCatalogueDrug>(item);
                            if (catalogueDrugs.Any(a => a.DrugCode == item.DrugCode))
                                catalogueDrugs.RemoveAll(a => a.DrugCode == item.DrugCode);
                            catalogueDrugs.Add(catalogueDrug);
                            if (catalogueDrugs != null && catalogueDrugs.Count > 50)
                            {
                                HisDbContext.InsurWorkInjuryCatalogueDrugs.AddRange(catalogueDrugs);
                                HisDbContext.SaveChanges();
                                catalogueDrugs.Clear();
                            }
                        }
                        if (catalogueDrugs != null && catalogueDrugs.Count > 0)
                        {
                            HisDbContext.InsurWorkInjuryCatalogueDrugs.AddRange(catalogueDrugs);
                            HisDbContext.SaveChanges();
                            catalogueDrugs.Clear();
                        }
                        

                        ////var strings= drugs.Select(s => s.DrugCode);
                        ////var injuryCatalogueDrugs = HisDbContext.InsurWorkInjuryCatalogueDrugs.Where(a => strings.Contains(a.DrugCode)).ToList();
                        ////if (injuryCatalogueDrugs is not null)
                        ////    HisDbContext.InsurWorkInjuryCatalogueDrugs.RemoveRange(injuryCatalogueDrugs);
                        //var catalogueDrugs = Mapper.Map<List<InsurWorkInjuryCatalogueDrug>>(drugs);
                        //HisDbContext.InsurWorkInjuryCatalogueDrugs.AddRange(catalogueDrugs);
                        //HisDbContext.SaveChanges();
                        break;
                    case "02"://项目
                        var treatmentItems = FileSerialize<TreatmentItem>(this.FileFullName);
                        List<InsurWorkInjuryCatalogueTreatmentItem> catalogueTreatmentItems = new List<InsurWorkInjuryCatalogueTreatmentItem>();
                        foreach (var item in treatmentItems)
                        {
                            if (HisDbContext.InsurWorkInjuryCatalogueTreatmentItems.Any(a => a.ItemCode == item.ItemCode))
                            {
                                var catalogueTreatmentItem = HisDbContext.InsurWorkInjuryCatalogueTreatmentItems.Find(item.ItemCode);
                                HisDbContext.InsurWorkInjuryCatalogueTreatmentItems.Remove(catalogueTreatmentItem);
                            }
                            var treatmentItem = Mapper.Map<InsurWorkInjuryCatalogueTreatmentItem>(item);
                            if (catalogueTreatmentItems.Any(a => a.ItemCode == item.ItemCode))
                                catalogueTreatmentItems.RemoveAll(a => a.ItemCode == item.ItemCode);
                            catalogueTreatmentItems.Add(treatmentItem);
                            if (catalogueTreatmentItems != null && catalogueTreatmentItems.Count > 50)
                            {
                                HisDbContext.InsurWorkInjuryCatalogueTreatmentItems.AddRange(catalogueTreatmentItems);
                                HisDbContext.SaveChanges();
                                catalogueTreatmentItems.Clear();
                            }
                        }
                        if (catalogueTreatmentItems != null && catalogueTreatmentItems.Count > 0)
                        {
                            HisDbContext.InsurWorkInjuryCatalogueTreatmentItems.AddRange(catalogueTreatmentItems);
                            HisDbContext.SaveChanges();
                            catalogueTreatmentItems.Clear();
                        }
                        break;
                    case "04"://病种编码
                        var diseaseCatalogues = FileSerialize<InsurWorkInjuryDiseaseCatalogue>(this.FileFullName);
                        List<InsurWorkInjuryDiseaseCatalogue> downDiseaseCatalogues = new List<InsurWorkInjuryDiseaseCatalogue>();
                        foreach (var item in diseaseCatalogues)
                        {
                            if (HisDbContext.InsurWorkInjuryDiseaseCatalogues.Any(a => a.Jbbm == item.Jbbm))
                            {
                                var catalogueTreatmentItem = HisDbContext.InsurWorkInjuryDiseaseCatalogues.Find(item.Jbbm);
                                HisDbContext.InsurWorkInjuryDiseaseCatalogues.Remove(catalogueTreatmentItem);
                            }
                            if (downDiseaseCatalogues.Any(a => a.Jbbm == item.Jbbm))
                                downDiseaseCatalogues.RemoveAll(a => a.Jbbm == item.Jbbm);
                            downDiseaseCatalogues.Add(item);
                            if (downDiseaseCatalogues != null && downDiseaseCatalogues.Count > 50)
                            {
                                HisDbContext.InsurWorkInjuryDiseaseCatalogues.AddRange(downDiseaseCatalogues);
                                HisDbContext.SaveChanges();
                                downDiseaseCatalogues.Clear();
                            }
                        }
                        if (downDiseaseCatalogues != null && downDiseaseCatalogues.Count > 0)
                        {
                            HisDbContext.InsurWorkInjuryDiseaseCatalogues.AddRange(downDiseaseCatalogues);
                            HisDbContext.SaveChanges();
                            downDiseaseCatalogues.Clear();
                        }
                        break;
                    case "11"://辅助器具
                        var auxiliaryEquipment = FileSerialize<InsurWorkInjuryAuxiliaryEquipment>(this.FileFullName);
                        List<InsurWorkInjuryAuxiliaryEquipment> downAuxiliaryEquipment = new List<InsurWorkInjuryAuxiliaryEquipment>();
                        foreach (var item in auxiliaryEquipment)
                        {
                            if (HisDbContext.InsurWorkInjuryAuxiliaryEquipments.Any(a => a.Fzqjbm == item.Fzqjbm))
                            {
                                var catalogueTreatmentItem = HisDbContext.InsurWorkInjuryAuxiliaryEquipments.Find(item.Fzqjbm);
                                HisDbContext.InsurWorkInjuryAuxiliaryEquipments.Remove(catalogueTreatmentItem);
                            }
                            if (downAuxiliaryEquipment.Any(a => a.Fzqjbm == item.Fzqjbm))
                                downAuxiliaryEquipment.RemoveAll(a => a.Fzqjbm == item.Fzqjbm);
                            downAuxiliaryEquipment.Add(item);
                            if (downAuxiliaryEquipment != null && downAuxiliaryEquipment.Count > 50)
                            {
                                HisDbContext.InsurWorkInjuryAuxiliaryEquipments.AddRange(downAuxiliaryEquipment);
                                HisDbContext.SaveChanges();
                                downAuxiliaryEquipment.Clear();
                            }
                        }
                        if (downAuxiliaryEquipment != null && downAuxiliaryEquipment.Count > 0)
                        {
                            HisDbContext.InsurWorkInjuryAuxiliaryEquipments.AddRange(downAuxiliaryEquipment);
                            HisDbContext.SaveChanges();
                            downAuxiliaryEquipment.Clear();
                        }
                        break;
                    default:
                        break;
                }
            });
        }

        [RelayCommand]
        private void OnOpenFile(object param)
        {
            OpenFileDialog openFileDialog =
            new()
            {
                //InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                InitialDirectory = AppDomain.CurrentDomain.BaseDirectory,
                Filter = "All files (*.txt)|*.txt"
            };

            if (openFileDialog.ShowDialog() != true)
            {
                return;
            }

            if (!File.Exists(openFileDialog.FileName))
            {
                return;
            }

            FileFullName = openFileDialog.FileName;
        }

        private List<T> FileSerialize<T>(string fileName)
            where T : new()
        {
            var resultList = new List<T>();
            Type type = typeof(T);
            var propertyInfos = type.GetProperties();
            List<string> lines = ReadFileByLines(this.FileFullName);
            int count = lines.Count <= propertyInfos.Length ? lines.Count : propertyInfos.Length;
            foreach (string line in lines)
            {
                T result = new T();
                var fileValues = line.Split('\t');
                for (int i = 0; i < count; i++)
                {
                    propertyInfos[i].SetValue(result, fileValues[i]);
                }
                resultList.Add(result);
            }
            return resultList;
        }
        private List<string> ReadFileByLines(string fileName)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            List<string> reList = new List<string>();

            StreamReader sr = new StreamReader(fileName, Encoding.GetEncoding("GB2312"));
            while (!sr.EndOfStream)
            {
                string line = sr.ReadLine();
                if (line != null)
                {
                    reList.Add(line);
                }
            }
            sr.Close();
            return reList;
        }
    }
}
